package watcher

import (
	"os"
	"bytes"
	"fmt"
	"time"
	"strings"
)

/*
func (ss *SshServer) handle(session ssh.Session) {
    input := session.Command()
    addr := chop(session.RemoteAddr().String())
    user := session.User()
    s := fmt.Sprintf("%s@%s", user, addr)
    ss.handleAuth(session, input, user, addr)
    LOG.Info("%s: start interactive", s)
    if err := ss.exec(session, s, input); err != nil {
        io.WriteString(session, "\n"+err.Error()+"\n")
        LOG.Error("%s: run command error %v", s, err)
        session.Exit(2)
    }
    LOG.Info("%s: finish interactive", s)
    session.Exit(0)
}
 */

type Exporter func(map[string]string) (string, error)

func (pws *ProcWatcherService) Export(tags map[string]string) (string, error) {
	ret := make(map[string][]string)
    pws.mu.Lock()
    defer pws.mu.Unlock()
	if err := pws.scan(); err != nil {
		return "", err
	}
	_, ok := tags["host"]
	if !ok {
		hostname, err := os.Hostname()
		if err == nil {
			tags["host"] = hostname
		}
	}
	pws.mu.RLock()
	defer pws.mu.RUnlock()
	var buf bytes.Buffer
	for k, v := range tags {
		buf.WriteString(fmt.Sprintf(`%s="%s", `, k, v))
	}
	str := buf.String()
	for pname, v := range pws.procs {
		stat, err := v.process.Status()
		if err != nil {
			return "", err
		}
		if IsNull(stat) {
			continue
		}
		duration := v.process.Uptime()
		name := fmt.Sprintf(`%s proc_name="%s"`, str, pname)
		ts := time.Now().Unix() * 1000
		format := "%s{%s} %d %d"
		ret["proc_uptime"] = append(ret["proc_uptime"],
			fmt.Sprintf(format, "proc_uptime", name, duration, ts))
		ret["proc_cutime"] = append(ret["proc_cutime"],
			fmt.Sprintf(format, "proc_cutime", name, stat.CuTime, ts))
		ret["proc_cstime"] = append(ret["proc_cstime"],
			fmt.Sprintf(format, "proc_cstime", name, stat.CsTime, ts))
		ret["proc_stime"] = append(ret["proc_stime"],
			fmt.Sprintf(format, "proc_stime", name, stat.STime, ts))
		ret["proc_blkio_ticks"] = append(ret["proc_blkio_ticks"],
			fmt.Sprintf(format, "proc_blkio_ticks", name, stat.BlkioTicks, ts))
		ret["proc_utime"] = append(ret["proc_utime"],
			fmt.Sprintf(format, "proc_utime", name, stat.UTime, ts))
		ret["proc_mem_size"] = append(ret["proc_mem_size"],
			fmt.Sprintf(format, "proc_mem_size", name, stat.MemSize, ts))
		ret["proc_thread_count"] = append(ret["proc_thread_count"],
			fmt.Sprintf(format, "proc_thread_count", name, stat.ThreadCount, ts))
		ret["proc_count"] = append(ret["proc_count"],
			fmt.Sprintf(format, "proc_count", name, stat.ProcCount, ts))
		var s []string
		for k, v := range stat.TcpCount {
			s = append(s, fmt.Sprintf(format, "proc_tcp_count", fmt.Sprintf(`%s,status="%s"`, name, k), v, ts))
		}
		if len(s) > 0 {
			ret["proc_tcp_count"] = append(ret["proc_tcp_count"], strings.Join(s, "\n"))
		}
	}
	buf.Reset()
	for k, v := range ret {
		s := fmt.Sprintf("# TYPE %s gauge\n", k)
		if k == "proc_uptime" {
			s = fmt.Sprintf("# TYPE %s counter\n", k)
		}
		buf.WriteString(s)
		for _, l := range v {
			buf.WriteString(l)
			buf.WriteString("\n")
		}
	}
	return buf.String(), nil
}
